/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ar.edu.unicen.twitter.suggest.frontend.controllers;

import ar.edu.unicen.twitter.suggest.backend.datasources.TwitterFacade;
import ar.edu.unicen.twitter.suggest.backend.dtos.RecommendationReport;
import ar.edu.unicen.twitter.suggest.backend.dtos.UsuarioProxy;
import ar.edu.unicen.twitter.suggest.backend.recommendation.CriterioUsuario.CriterioFuente;
import ar.edu.unicen.twitter.suggest.backend.recommendation.CriterioUsuario.CriterioTodos;
import ar.edu.unicen.twitter.suggest.backend.recommendation.CriterioUsuario.CriterioUsuario;
import ar.edu.unicen.twitter.suggest.backend.recommendation.crawling.NivelRecoleccion;
import ar.edu.unicen.twitter.suggest.backend.recommendation.crawling.Recolector;
import ar.edu.unicen.twitter.suggest.backend.services.RecommendationControllerInterface;
import ar.edu.unicen.twitter.suggest.commons.dtos.Usuario;
import ar.edu.unicen.twitter.suggest.frontend.charts.graph.Graph;
import ar.edu.unicen.twitter.suggest.frontend.charts.graph.Node;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.RejectedException;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.TwitterException;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.UserNotFoundException;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.UserProtectedException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 *
 * @author Alex
 */
@Controller("suggestController")
public class SuggestController {

     private final static Logger LOGGER = Logger.getLogger(SuggestController.class.getName());
    @Autowired
    TwitterFacade twitterFacade;
    @Autowired
    RecommendationControllerInterface recommendationController;
    private long userId = 1004662;
    private String screenName = "jasigno";
    private int nivelIntermedio = 200;
    private int nivelFinal = 20;
    private int MAXSEGUIDOS = 5000;
    private UsuarioProxy user;
    static Random random = new Random();
    static CriterioUsuario criterioTodos = new CriterioTodos();
    static CriterioUsuario criterioFuente = new CriterioFuente();
    private Collection<Usuario> fuentes;
    private Collection<Usuario> amigos;
    private Collection<Usuario> interseccion;
    private Collection<Usuario> union;
    private Long elapsedTime;
    private boolean permitirRedundancia = false;

    private List<RecommendationReport> reportes;
    private RecommendationReport reporteAmigos;
    private RecommendationReport reporteFuentes;
    private RecommendationReport reporteUnion;
    private RecommendationReport reporteInterseccion;
    
    public SuggestController() {
    }

    public void search() {
        try {
            this.user = (UsuarioProxy) twitterFacade.getUser(screenName);
            userId = this.user.getId();
            Date inicio = new Date();
            reportes = recommendationController.recomendar(userId, nivelIntermedio, nivelFinal, MAXSEGUIDOS, 1, 0, permitirRedundancia);
            for(RecommendationReport reporte: reportes)
            {
                
                if(reporte.getMetodo() == RecommendationReport.METODO_AMIGOS){
                   reporteAmigos = reporte;
                   amigos = reporteAmigos.getRecomendacion();
                   
                }
                else if(reporte.getMetodo() == RecommendationReport.METODO_FUENTES){
                   reporteFuentes = reporte;
                   fuentes = reporteFuentes.getRecomendacion();
                }
                else if(reporte.getMetodo() == RecommendationReport.METODO_UNION){
                   reporteUnion = reporte;
                   union = reporteUnion.getRecomendacion();
                }
                elapsedTime = new Date().getTime() - inicio.getTime();
            }
        } catch (UserNotFoundException ex) {
            Logger.getLogger(SuggestController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UserProtectedException ex) {
            Logger.getLogger(SuggestController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RejectedException ex) {
            Logger.getLogger(SuggestController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TwitterException ex) {
            Logger.getLogger(SuggestController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getScreenName() {
        return screenName;
    }

    public void setScreenName(String screenName) {
        this.screenName = screenName;
    }

    public Usuario getResultUser() {
        return user;
    }

    public Collection<Usuario> getFuentes() {
        return fuentes;
    }

    public Collection<Usuario> getAmigos() {
        return amigos;
    }

    public Collection<Usuario> getInterseccion() {
        return interseccion;
    }

    public Collection<Usuario> getUnion() {
        return union;
    }

    public int getNivelIntermedio() {
        return nivelIntermedio;
    }

    public int getNivelFinal() {
        return nivelFinal;
    }

    public void setNivelIntermedio(int nivelIntermedio) {
        this.nivelIntermedio = nivelIntermedio;
    }

    public void setNivelFinal(int nivelFinal) {
        this.nivelFinal = nivelFinal;
    }

    public Long getElapsedTime() {
        return elapsedTime;
    }

    public Graph getGraph(Recolector recolector) {
        Graph graph = new Graph();
        Map<Long/*usuario*/, Long/*nodo*/> indiceUsuarios = new HashMap<Long/*usuario*/, Long/*nodo*/>();
        if (recolector != null) {
            List<ArrayList<Usuario>> arbol = recolector.getArbol();
            List<NivelRecoleccion> niveles = recolector.getNiveles();
            
            for (int n = 0; n < niveles.size(); ++n) {
                for (int u = 0; u < arbol.get(n).size(); ++u) {
                    Usuario usuario = arbol.get(n).get(u);
                    Node node = new Node(usuario.getId(), usuario.getScreenName(), usuario.getMentions());
                    long index = graph.addNode(node);
                    indiceUsuarios.put(usuario.getId(), index);
                }
            }
            for (int n = 0; n < niveles.size(); ++n) {
                for (int u = 0; u < arbol.get(n).size(); ++u) {
                    Usuario usuario = arbol.get(n).get(u);
                    long origen = indiceUsuarios.get(usuario.getId());
                    Collection<Usuario> followers = niveles.get(n).getSiguientes(usuario);
                    for (Usuario follower:followers) {
                        Long destino = indiceUsuarios.get(follower.getId());
                        if (destino != null) {
                            graph.addLink(origen, destino);
                        }
                    }
                }
            }
        }
        return graph;
    }
    public Graph getGraphFuentes() {
        return getGraph(reporteFuentes.getRecolector());
    }
}
